package com.atguigu.tingshu.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public UserInfoVo getUserInfoVoByUserId(Long userId) {
        UserInfo userInfo = getById(userId);
        return BeanUtil.copyProperties(userInfo, UserInfoVo.class);
    }

    @Override
    public Boolean isSubscribe(Long albumId) {
        Long userId = AuthContextHolder.getUserId();
        if (userId == null) return false;
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_SUBSCRIBE, userId);
        UserSubscribe userSubscribe = mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId).and("albumId").is(albumId)),
                UserSubscribe.class, collectionName);
        return userSubscribe == null ? false : true;
    }

    @Override
    public void updateExpiredVipStatus() {
        this.lambdaUpdate().eq(UserInfo::getIsVip, 1)
                .le(UserInfo::getVipExpireTime, new Date())
                .set(UserInfo::getIsVip, 0).update();
    }

    @Override
    public void makeOrderPaidInfo(UserPaidRecordVo userPaidRecordVo) {
        String orderNo = userPaidRecordVo.getOrderNo();
        Long userId = userPaidRecordVo.getUserId();
        List<Long> itemIdList = userPaidRecordVo.getItemIdList();
        // 判断订单类型，进行不同的处理
        String itemType = userPaidRecordVo.getItemType();
        switch (itemType) {
            case SystemConstant.ORDER_ITEM_TYPE_ALBUM:
                // 记录该专辑的购买记录
                Long albumId = itemIdList.get(0);
                Db.save(new UserPaidAlbum().setUserId(userId).setOrderNo(orderNo).setAlbumId(albumId));
                // TODO: 发送消息给专辑记录专辑的购买次数
                break;
            case SystemConstant.ORDER_ITEM_TYPE_TRACK:
                // 根据声音的id查询声音
                Result<TrackInfo> trackInfoResult = this.trackInfoFeignClient.getTrackInfo(itemIdList.get(0));
                Assert.notNull(trackInfoResult, "记录声音的购买记录时，获取声音信息失败！" + itemIdList.get(0));
                TrackInfo trackInfo = trackInfoResult.getData();
                // 遍历声音的id集合进行声音购买行为的记录
                List<UserPaidTrack> collect = itemIdList.stream().map(itemId -> {
                    UserPaidTrack userPaidTrack = new UserPaidTrack();
                    userPaidTrack.setOrderNo(orderNo);
                    userPaidTrack.setUserId(userId);
                    userPaidTrack.setTrackId(itemId);
                    userPaidTrack.setAlbumId(trackInfo.getAlbumId());
                    return userPaidTrack;
                }).collect(Collectors.toList());
                Db.saveBatch(collect);
                break;
                // todo:新增用户的声音购买记录
            case SystemConstant.ORDER_ITEM_TYPE_VIP:
                // 根据订单编号查询同一个订单的vip是否已经记录过
                UserVipService userVipService = Db.lambdaQuery(UserVipService.class).eq(UserVipService::getOrderNo, orderNo).one();
                if (userVipService != null){
                    // 如果已经记录过 则直接结束
                    return;
                }
                // 根据套餐id查询vip套餐
                VipServiceConfig vipServiceConfig = Db.lambdaQuery(VipServiceConfig.class).eq(VipServiceConfig::getId, itemIdList.get(0)).one();
                Integer serviceMonth = vipServiceConfig.getServiceMonth();
                // 查询用户
                UserInfo userInfo = this.getById(userId);
                // 判断当前用户是否已经是vip
                Date expire = userInfo.getVipExpireTime();
                LocalDateTime expireTime = LocalDateTime.now();
                if (expire != null){
                    expireTime =  LocalDateTime.fromDateFields(expire);
                }
                LocalDateTime startTime = LocalDateTime.now();
                if (userInfo.getIsVip().intValue() == 1 && expire.after(new Date())){
                    // 如果是vip则续期
                    userInfo.setVipExpireTime(expireTime.plusMonths(serviceMonth).toDate());
                    // 如果是vip则vip的服务起始时间应该是vip过期时间的第二天
                    startTime = expireTime.plusDays(1);
                } else {
                    // 如果不是vip则修改vip状态，并设置过期时间(当前时间 + serviceMonth - 1天)
                    userInfo.setIsVip(1);
                    userInfo.setVipExpireTime(LocalDateTime.now().plusMonths(serviceMonth).minusDays(1).toDate());
                }
                // 更新
                this.updateById(userInfo);

                // 记录vip的购买行为
                userVipService = new UserVipService();
                userVipService.setOrderNo(orderNo);
                userVipService.setUserId(userId);
                userVipService.setStartTime(startTime.toDate());
                // 过期时间 = 起始时间 + 服务月份 - 1天
                userVipService.setExpireTime(startTime.plusMonths(serviceMonth).minusDays(1).toDate());
                Db.save(userVipService);
                break;
        }
    }
}
